package jmine.tec.hydra.processor;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jmine.tec.hydra.HydraController;
import jmine.tec.hydra.HydraMessages;
import jmine.tec.hydra.domain.HydraSystem;
import jmine.tec.hydra.driver.HydraBean;
import bancosys.tec.datadigester.DataDigesterException;
import bancosys.tec.datadigester.DigesterBean;
import bancosys.tec.datadigester.processor.AbstractProcessor;
import bancosys.tec.persist.dao.BaseDAO;
import bancosys.tec.persist.dao.BeanNotFoundException;

/**
 * Processor de integração generica utilizando o Hydra.
 * 
 * @author Rafael Volpato
 */
public class HydraProcessor extends AbstractProcessor {
    public static final String FILENAME = "filename";

    public static final String FILECODE = "filecode";

    // (qualquer_coisa\)?qualquer_coisa_obrigatoria-qualquer_coisa_obrigatoria.?qualquercoisaopcional
    // Formato: systemname-filecode
    // Exemplo: PEGASUS-FUNDO.xml
    private static final Pattern PATTERN_FILENAME = Pattern.compile("(?:.*\\\\)?([A-Za-z]+)\\-([A-Za-z]+)\\.?.*");

    private HydraController hydraController;

    /**
     * @return the hydraController
     */
    public HydraController getHydraController() {
        return this.hydraController;
    }

    /**
     * @param hydraController the hydraController to set
     */
    public void setHydraController(HydraController hydraController) {
        this.hydraController = hydraController;
    }

    /**
     * Retorna o codigo da mensagem baseado no nome do arquivo.
     * 
     * @param bean hydraBean
     * @return o codigo da mensagem baseado no nome do arquivo
     */
    protected String getCodigoMensagem(HydraBean bean) {
        Matcher matcher = PATTERN_FILENAME.matcher(bean.getFilename());
        if (matcher.matches()) {
            return matcher.group(2);
        } else {
            throw new DataDigesterException(HydraMessages.RECEIVE_FILE_MESSAGE_CODE.create(bean.getFilename()));
        }
    }

    /**
     * Retorna o sistema de origem baseado no nome do arquivo.
     * 
     * @param bean hydraBean
     * @return o sistema de origem baseado no nome do arquivo
     */
    protected String getSistemaOrigem(HydraBean bean) {
        Matcher matcher = PATTERN_FILENAME.matcher(bean.getFilename());
        if (matcher.matches()) {
            return matcher.group(1);
        } else {
            throw new DataDigesterException(HydraMessages.RECEIVE_FILE_MESSAGE_CODE.create(bean.getFilename()));
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void doProcess(DigesterBean bean) {
        HydraBean hydraBean = (HydraBean) bean;
        try {
            BaseDAO<HydraSystem> dao = this.hydraController.getDAOFactory().getGenericDAO(HydraSystem.class);
            Map<String, String> messageProperties = new HashMap<String, String>();

            HydraSystem hydraSystem = dao.findByNaturalKey(this.getSistemaOrigem(hydraBean));
            messageProperties.put(HydraProcessor.FILENAME, hydraBean.getFilename());
            messageProperties.put(HydraProcessor.FILECODE, this.getCodigoMensagem(hydraBean));

            this.hydraController.receive(hydraSystem, hydraBean.getInputStream(), messageProperties);
        } catch (BeanNotFoundException e) {
            throw new DataDigesterException(HydraMessages.RECEIVE_MQ_RECEIVER.create(), e);
        }
    }
}
